package com.markerhub.common.shiro;

import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.markerhub.common.UserType;
import com.markerhub.entity.User;
import com.markerhub.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 类名称：自定义realm
 * 类描述：自定义了认证和授权过程
 */
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    /**
     * 认证，也就是确认登录的账户密码是否正确
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //这里参数里的token就是subject.login(token)传进来的token
        MyLoginToken myLoginToken= (MyLoginToken) authenticationToken;
        //获取用户类型
        String loginType = myLoginToken.getLoginType();
        //获取到身份信息，系统以联系方式位账号登录
        String username = myLoginToken.getUsername();
        //根据不同用户类型查不同表
        User user= userService.finduserByUserName(username);
        if(!ObjectUtils.isEmpty(user)){
            //交给shiro进行验证，shiro将数据库中的信息和用户输入的信息进行比对
            //第一个参数可以通过SecurityUtils.getSubject().getPrincipal()可在其他地方获取，可存放任意数据类型，与加密无关；
            // 第二个参数是加密后的数据，也可以是未加密的明文，取决于HashedCredentialsMatcher如何配置，
            // 用于比对的明文是AuthenticationToken实现类的getCredentials()重写方法返回的值；
            // 第三个参数加密的盐（可选添加）,
            // 第四个通过getName()配置。
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    user,
                    user.getPassword(),
                    ByteSource.Util.bytes(user.getSalt()),
                    this.getName());
            //从shiro拿到session,把用户信息放入session
            Session session = SecurityUtils.getSubject().getSession();
            //再session中放入session信息
            if(loginType.equals(UserType.USER) ){
                session.setAttribute("loginType",UserType.USER);
            }else if(loginType.equals(UserType.ADMIN)){
                session.setAttribute("loginType",UserType.ADMIN);
            }
            return simpleAuthenticationInfo;
        }
        else{
            throw new UnknownAccountException();
        }
    }
}
